import os
import json
import threading
from typing import Dict, Any, List

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer


class FTPServerManager:
    """管理 pyftpdlib FTP 服务，支持动态添加账户、匿名访问与根目录切换。"""

    def __init__(self, config_path: str = "config.json"):
        self.config_path = config_path
        self.authorizer = DummyAuthorizer()
        self.handler = FTPHandler
        self.handler.authorizer = self.authorizer

        self.server = None
        self.server_thread: threading.Thread | None = None
        self.lock = threading.Lock()

        self.host = "0.0.0.0"
        self.port = 2121
        self.root_dir = os.path.abspath("ftp_root")
        self.banner = "欢迎使用教学FTP服务器"
        # 可选：限制被动端口范围，便于防火墙放行
        self.passive_ports = range(30000, 30050)

        # 记录用户配置（不含明文密码以外的信息）
        self.users: Dict[str, Dict[str, Any]] = {}
        self.anonymous_enabled = False
        self.anonymous_perm = "elr"  # 默认匿名只读权限

        self.load_config()

    # ------------------------------- 配置读写 -------------------------------
    def load_config(self) -> None:
        if os.path.exists(self.config_path):
            with open(self.config_path, "r", encoding="utf-8") as f:
                cfg = json.load(f)
            self.host = cfg.get("host", self.host)
            self.port = int(cfg.get("port", self.port))
            self.root_dir = os.path.abspath(cfg.get("root_dir", self.root_dir))
            self.users = cfg.get("users", {})
            self.anonymous_enabled = cfg.get("anonymous_enabled", False)
            self.anonymous_perm = cfg.get("anonymous_perm", self.anonymous_perm)

        os.makedirs(self.root_dir, exist_ok=True)
        self._rebuild_authorizer()

    def save_config(self) -> None:
        cfg = {
            "host": self.host,
            "port": self.port,
            "root_dir": self.root_dir,
            "users": self.users,
            "anonymous_enabled": self.anonymous_enabled,
            "anonymous_perm": self.anonymous_perm,
        }
        with open(self.config_path, "w", encoding="utf-8") as f:
            json.dump(cfg, f, ensure_ascii=False, indent=2)

    # ------------------------------- 内部方法 -------------------------------
    def _rebuild_authorizer(self) -> None:
        """根据当前配置重建授权器。"""
        self.authorizer = DummyAuthorizer()
        self.handler.authorizer = self.authorizer

        # 添加普通用户（家目录统一指向 root_dir）
        for username, info in self.users.items():
            perm = info.get("perm", "elradfmwMT")
            password = info.get("password", "")
            self.authorizer.add_user(username, password, self.root_dir, perm=perm)

        # 添加匿名用户（如启用）
        if self.anonymous_enabled:
            try:
                self.authorizer.add_anonymous(self.root_dir, perm=self.anonymous_perm)
            except Exception:
                # 若已存在则忽略
                pass

    # ------------------------------- 服务控制 -------------------------------
    def start(self, host: str | None = None, port: int | None = None) -> None:
        with self.lock:
            if host:
                self.host = host
            if port:
                self.port = int(port)
            if self.server:
                return

            address = (self.host, self.port)
            handler = self.handler
            handler.banner = self.banner
            try:
                handler.passive_ports = self.passive_ports
            except Exception:
                pass

            self.server = FTPServer(address, handler)
            self.server_thread = threading.Thread(target=self.server.serve_forever, daemon=True)
            self.server_thread.start()

    def stop(self) -> None:
        with self.lock:
            if self.server:
                try:
                    self.server.close_all()
                except Exception:
                    pass
                self.server = None
                self.server_thread = None

    def restart(self) -> None:
        self.stop()
        self.start()

    # ------------------------------- 配置操作 -------------------------------
    def set_root_dir(self, path: str) -> None:
        path = os.path.abspath(path)
        os.makedirs(path, exist_ok=True)
        self.root_dir = path
        self._rebuild_authorizer()
        self.save_config()

    def add_user(self, username: str, password: str, perm: str = "elradfmwMT") -> None:
        self.users[username] = {"password": password, "perm": perm}
        self.authorizer.add_user(username, password, self.root_dir, perm=perm)
        self.save_config()

    def remove_user(self, username: str) -> None:
        try:
            self.authorizer.remove_user(username)
        except Exception:
            pass
        self.users.pop(username, None)
        self.save_config()

    def enable_anonymous(self, perm: str = "elr") -> None:
        self.anonymous_enabled = True
        self.anonymous_perm = perm
        try:
            self.authorizer.add_anonymous(self.root_dir, perm=perm)
        except Exception:
            # 如已存在，重建授权器保证一致
            self._rebuild_authorizer()
        self.save_config()

    def disable_anonymous(self) -> None:
        self.anonymous_enabled = False
        try:
            # DummyAuthorizer 支持当作普通用户名移除
            self.authorizer.remove_user("anonymous")
        except Exception:
            self._rebuild_authorizer()
        self.save_config()

    # ------------------------------- 状态查询 -------------------------------
    def status(self) -> Dict[str, Any]:
        return {
            "running": bool(self.server),
            "host": self.host,
            "port": self.port,
            "root_dir": self.root_dir,
            "users": [{"username": k, "perm": v.get("perm", "elradfmwMT")} for k, v in self.users.items()],
            "anonymous_enabled": self.anonymous_enabled,
            "anonymous_perm": self.anonymous_perm,
        }